`include "C:\Users\lenovo\Desktop\Files\Linear_RISCV\LR_ver_0\src\include\include.vh"
module 	Linear_RISC_top(
    input				clk,
    input				rst_n,
    input				ena,
    output  [63:0]      data_o,
    output  [63:0]      pc_o     
);

wire [3:0] flush;
wire flush_0,flush_1,flush_2,flush_3;
assign flush_0 = flush[0];
assign flush_1 = flush[1];
assign flush_2 = flush[2];
assign flush_3 = flush[3];

wire [3:0] pip_ena;
wire ena_0,ena_1,ena_2,ena_3;
assign ena_0 = pip_ena[0];
assign ena_1 = pip_ena[1];
assign ena_2 = pip_ena[2];
assign ena_3 = pip_ena[3];


wire [63:0] pc_flush_i;
wire        branch_taken_i,branch_taken;

wire [63:0] pc_if;
wire [31:0] instr_if;
wire [63:0] PC_new;

ifu  inst_ifu (
    .clk               (clk),
    .rst_n             (rst_n),
    .ena               (ena_0),
    .pc_flush_i        (PC_new),
    .branch_taken_i    (branch_taken_i),
    .instr_if_o        (instr_if),
    .pc_if_o           (pc_if)
);

assign pc_o = pc_if; 
wire [63:0] PC_id;
wire [31:0] instr_id;

if_id_u  inst_if_id_u (
    .clk               (clk),
    .rst_n             (rst_n),
    .flush             (flush_0),
    .ena               (ena_0),
    .PC_ifu            (pc_if),
    .PC_idu            (PC_id),
    .instr_ifu         (instr_if),
    .instr_idu         (instr_id)
);

wire [63:0] Rd_wb,Rd_wb_o;
assign data_o = Rd_wb_o;

wire [4: 0] rd_wb;
wire        RegW_wb;

wire  [5:0]  uop_code_id;
wire  [3:0]  exe_type_id;

wire [4: 0] rs1_id,rs2_id;
wire [63:0] Rs1_id,Rs2_id;
wire [4: 0] rd_id;
wire [63:0] imm_id;

wire [4: 0] ctrl_id;

idu  inst_idu (
    .clk               (clk),
    .rst_n             (rst_n),
    .instr             (instr_id),
    .rd_i              (rd_wb),
    .Rd_i              (Rd_wb_o),
    .RegWrite_i        (RegW_wb),
    .uop_code          (uop_code_id),
    .exe_type          (exe_type_id),
    .rd                (rd_id),
    .rs1               (rs1_id),
    .rs2               (rs2_id),
    .Rs1               (Rs1_id),
    .Rs2               (Rs2_id),
    .ctrl_bus          (ctrl_id),
    .imm_o             (imm_id)
);

wire  [5:0]  uop_code_ex;
wire  [3:0]  exe_type_ex;

wire [4: 0] rs1_ex,rs2_ex;
wire [63:0] Rs1_ex,Rs2_ex;
wire [63:0] imm_ex;
wire [4: 0] rd_ex;

wire [63:0] PC_ex;

id_ex_u  inst_id_ex_u (
    .clk               (clk),
    .rst_n             (rst_n),
    .flush             (flush_1),
    .ena               (ena_1),
    .Rs1_idu_i         (Rs1_id),
    .Rs1_exu_o         (Rs1_ex),
    .Rs2_idu_i         (Rs2_id),
    .Rs2_exu_o         (Rs2_ex),
    .imm_idu_i         (imm_id),
    .imm_exu_o         (imm_ex),
    .PC_idu_i          (PC_id),
    .PC_exu_o          (PC_ex),
    .uop_code_idu      (uop_code_id),
    .exe_type_idu      (exe_type_id),
    .uop_code_exu      (uop_code_ex),
    .exe_type_exu      (exe_type_ex),
    .rs1_idu_i         (rs1_id),
    .rs1_exu_o         (rs1_ex),
    .rs2_idu_i         (rs2_id),
    .rs2_exu_o         (rs2_ex),
    .ctrl_bus_idu      (ctrl_id),
    .ctrl_bus_exu      (ctrl_ex),
    .rd_idu_i          (rd_id),
    .rd_exu_o          (rd_ex)
);
    

wire [63:0]  Rd_ls;
wire [63:0]  alu_out_ex,store_ex;
wire  [2:0]  Load_sel_ex;
wire  [2:0]  ctrl_ex_o;

wire  [1:0]  forwar_1,forwar_2;

exu  inst_exu (
    .imm_exu_i         (imm_ex),
    .PC_exu_i          (PC_ex),
    .Rs1_exu_i         (Rs1_ex),
    .Rs2_exu_i         (Rs2_ex),
    .Rd_lsu            (Rd_ls),
    .Rd_wbu            (Rd_wb),
    .forwar_1          (forwar_1),
    .forwar_2          (forwar_2),
    .ctrl_bus_exu_i    (ctrl_ex),
    .uop_code          (uop_code_ex),
    .exe_type          (exe_type_ex),
    .exu_out           (alu_out_ex),
    .PC_exu            (pc_flush_i),
    .Store_data        (store_ex),
    .Load_sel_exu      (Load_sel_ex),
    .ctrl_bus_exu_o    (ctrl_ex_o),
    .Branch_taken      (branch_taken)
);

wire  [5:0]  uop_code_ls;
wire  [3:0]  exe_type_ls;

wire [63:0]  alu_out_ls;
wire [63:0]  store_ls;

wire  [2:0]  Load_sel_ls;
wire  [2:0]  ctrl_ls;

wire [4: 0] rd_ls;



ex_ls_u  inst_ex_ls_u (
    .clk               (clk),
    .rst_n             (rst_n),
    .flush             (flush_2),
    .ena               (ena_2),
    .exe_type_exu      (exe_type_ex),
    .exe_type_lsu      (exe_type_ls),
    .exu_out_exu       (alu_out_ex),
    .exu_out_lsu       (alu_out_ls),
    .Load_sel_exu      (Load_sel_ex),
    .Load_sel_lsu      (Load_sel_ls),
    .ctrl_bus_exu      (ctrl_ex_o),
    .ctrl_bus_lsu      (ctrl_ls),
    .Store_data_exu    (store_ex),
    .Store_data_lsu    (store_ls),
    .rd_exu            (rd_ex),
    .rd_lsu            (rd_ls)
);

wire [63:0]  load_out_ls;
wire         WB_sel_ls,Reg_W_ls;


lsu  inst_lsu (
    .clk               (clk),
    .rst_n             (rst_n),
    .exu_out           (alu_out_ls),
    .Store_data        (store_ls),
    .Load_sel_lsu      (Load_sel_ls),
    .exe_type          (exe_type_ls),
    .ctrl_bus_lsu      (ctrl_ls),
    .Load_data         (load_out_ls),
    .Rd_lsu            (Rd_ls),
    .WB_sel_lsu        (WB_sel_ls),
    .Reg_W_lsu         (Reg_W_ls)
);

wire [63:0]  load_out_wb;
wire         WB_sel_wb,Reg_W_wb;


ls_wb_u  inst_ls_wb_u (
    .clk               (clk),
    .rst_n             (rst_n),
    .flush             (flush_3),
    .ena               (ena_3),
    .WB_sel_lsu        (WB_sel_ls),
    .WB_sel_wbu        (WB_sel_wb),
    .Reg_W_lsu         (Reg_W_ls),
    .Reg_W_wbu         (Reg_W_wb),
    .Rd_lsu            (Rd_ls),
    .Rd_wbu            (Rd_wb),
    .Load_data_lsu     (load_out_ls),
    .Load_data_wbu     (load_out_wb),
    .rd_lsu            (rd_ls),
    .rd_wbu            (rd_wb)
);

wbu  inst_wbu (
    .WB_sel            (WB_sel_wb),
    .Load_data_wbu     (load_out_wb),
    .Rd_wbu_i          (Rd_wb),
    .Reg_W_wbu         (Reg_W_wb),
    .RegWrite_i        (RegWrite_i),
    .Rd_wbu_o          (Rd_wb_o)
);


main_ctrl_u  inst_main_ctrl_u (
    .clk               (clk),
    .rst_n             (rst_n),
    .ena               (ena),
    .branch_taken      (branch_taken),
    .PC_branch         (pc_flush_i),
    .flush             (flush),
    .pip_ena           (pip_ena),
    .PC_new            (PC_new),
    .branch_taken_i    (branch_taken_i)
);

forwarding_u  inst_forwarding_u (
    .rs1_i             (rs1_i),
    .rs2_i             (rs2_i),
    .rd_ls             (rd_ls),
    .rd_wb             (rd_wb),
    .forwar_1          (forwar_1),
    .forwar_2          (forwar_2)
);


endmodule